package com.oraro.paygatewaybiz.channel.wxpay.serviceImpl;

import com.github.wxpay.sdk.WXPay;
import com.oraro.common.result.Result;
import com.oraro.middleservice.logger.starter.supports.BizLoggerHelper;
import com.oraro.paygatewaybiz.channel.wxpay.proxy.WXPayServiceProxy;
import com.oraro.paygatewaybiz.constant.Constants;
import com.oraro.paygatewaybiz.exception.WXNotifyException;
import com.oraro.paygatewaybiz.interfaces.PayChannelService;
import com.oraro.paygatewaybiz.module.entity.ChannelEntity;
import com.oraro.paygatewaybiz.module.entity.MchEntity;
import com.oraro.paygatewaybiz.module.entity.OrderEntity;
import com.oraro.paygatewaybiz.module.service.ChannelService;
import com.oraro.paygatewaybiz.module.service.MchService;
import com.oraro.paygatewaybiz.module.service.OrderService;
import com.oraro.paygatewaybiz.utils.HttpsUtils;
import com.oraro.paygatewaybiz.utils.OrderValidator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;


/**
 * @Author: jianghuiyong
 * @Date: 2018/11/16 11:24
 * @Version 1.0
 */
@Service
@Slf4j
public class WXPayChannelServiceImpl extends AbstractWXBaseService implements PayChannelService {

    @Autowired
    private WXPayServiceProxy wxPayServiceProxy;
    @Autowired
    private ChannelService channelService;
    @Autowired
    private OrderService orderService;
    @Autowired
    private MchService mchService;
    @Autowired
    private BizLoggerHelper bizLoggerHelper;

    @Override
    public String type() {
        return Constants.PayChannelType.WXPAY.getType();
    }

    @Override
    public Result payOrder(OrderEntity orderEntity, ChannelEntity channelEntity) {
        return wxPayServiceProxy.payOrder(orderEntity, channelEntity);
    }

    @Override
    public String handleNotify(Map<String, String> reqMap, String channelType) {
        if (!"SUCCESS".equals(reqMap.get("return_code"))) {
            throw new WXNotifyException("微信回调参数错误");
        } else {
            //验证参数签名
            ChannelEntity channelEntity = channelService.getChannelByWXMch(reqMap.get("mch_id"), reqMap.get("appid"));
            if (channelEntity == null) {
                throw new WXNotifyException("微信渠道查询失败,订单号:" + reqMap.get("out_trade_no"));
            }
            WXPay wxPay = getWXPayInstance(channelEntity);
            boolean isPayResultNotifySignatureValid = false;
            try {
                isPayResultNotifySignatureValid = wxPay.isPayResultNotifySignatureValid(reqMap);
            } catch (Exception e) {
                throw new WXNotifyException("微信SIGN验证失败,订单号:{}" + reqMap.get("out_trade_no"));
            }
            if (!isPayResultNotifySignatureValid) {
                throw new WXNotifyException("微信SIGN验证失败,订单号:" + reqMap.get("out_trade_no"));
            }

            //验证本地订单金额
            OrderEntity orderEntity = orderService.getByTradeNo(reqMap.get("out_trade_no"));
            if (orderEntity == null) {
                throw new WXNotifyException("微信订单不存在,订单号:{}" + reqMap.get("out_trade_no"));
            }

            if (orderEntity.getPayStatus() == 0) {
                if (orderEntity.getTotalFee() != Long.parseLong(reqMap.get("total_fee"))) {
                    throw new WXNotifyException("微信订单金额错误,订单号:{}" + orderEntity.getOutTradeNo());

                }
                // 完成订单状态
                orderService.completeOrder(orderEntity);
                bizLoggerHelper.log("完成微信订单===========订单号===:{}" + orderEntity.getOutTradeNo());

                //回调本地商户notifyUrl
                MchEntity mchEntity = mchService.getById(orderEntity.getMchId());
                try {
                    Map<String, String> map = OrderValidator.generateNotifyParam(orderEntity, mchEntity.getMchKey());
                    notifyParam(channelEntity.getNotifyUrl(), map);
                } catch (Exception e) {
                    log.error(e.toString());
                    throw new WXNotifyException("微信回调本地服务失败,订单号" + orderEntity.getOutTradeNo());
                }
            }
        }
        Map<String, String> returnData = new HashMap<>();
        returnData.put("return_code", "SUCCESS");
        returnData.put("return_msg", "OK");
        return createWXxmlResult(returnData);
    }

    @Async
    public void notifyParam (String url, Map<String, String> map) {
        HttpsUtils.doPost(url, map);
    }

}
